package com.quiz.bis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quiz.bis.domain.model.*;
import com.quiz.bis.domain.vo.QuestionDetailVo;
import com.quiz.bis.mapper.*;
import com.quiz.bis.service.IQuestionService;
import com.quiz.bis.service.IWrongQuestionService;
import com.quiz.common.core.domain.R;
import com.quiz.common.mybatis.core.page.PageQuery;
import com.quiz.common.mybatis.core.page.TableDataInfo;
import com.quiz.common.mybatis.core.query.LambdaQueryWrapperPlus;
import com.quiz.common.mybatis.core.query.MPJLambdaWrapperPlus;
import com.quiz.common.mybatis.core.query.PlusWrappers;
import com.quiz.common.utils.DateUtils;
import com.quiz.common.utils.SecurityUtils;
import com.quiz.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 错题本服务层实现
 *
 * @author ahuan
 */
@Service
@RequiredArgsConstructor
public class WrongQuestionServiceImpl implements IWrongQuestionService {
    private final WrongQuestionBookMapper bookMapper;
    private final WrongQuestionRecordMapper recordMapper;
    private final WrongQuestionPracticeMapper practiceMapper;
    private final WrongQuestionStatsMapper statsMapper;
    private final QuestionMapper questionMapper;
    private final ExamQuestionAnswersMapper answerMapper;
    private final ExamStudentRecordMapper examStudentRecordMapper;
    private final ExamMapper examMapper;
    private final IQuestionService questionService;
    private final QuestionCategoryRelationMapper relationMapper;
    private final QuestionCategoryMapper categoryMapper;
    private final QuestionTypeMapper typeMapper;

    @Override
    public TableDataInfo<WrongQuestionBook> pageBookList(Long userId, PageQuery page) {
        LambdaQueryWrapper<WrongQuestionBook> lqw = Wrappers.lambdaQuery();
        lqw.eq(WrongQuestionBook::getUserId, userId)
                .eq(WrongQuestionBook::getDelFlag, 0)
                .orderByDesc(WrongQuestionBook::getIsDefault)
                .orderByDesc(WrongQuestionBook::getCreateTime);

        Page<WrongQuestionBook> result = bookMapper.selectPage(page.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public List<WrongQuestionBook> listBooks(Long userId) {
        LambdaQueryWrapper<WrongQuestionBook> lqw = Wrappers.lambdaQuery();
        lqw.eq(WrongQuestionBook::getUserId, userId)
                .eq(WrongQuestionBook::getDelFlag, 0)
                .orderByDesc(WrongQuestionBook::getIsDefault)
                .orderByDesc(WrongQuestionBook::getCreateTime);
        return bookMapper.selectList(lqw);
    }

    @Override
    public WrongQuestionBook getDefaultBook(Long userId) {
        LambdaQueryWrapper<WrongQuestionBook> lqw = Wrappers.lambdaQuery();
        lqw.eq(WrongQuestionBook::getUserId, userId)
                .eq(WrongQuestionBook::getIsDefault, 1)
                .eq(WrongQuestionBook::getDelFlag, 0);
        return bookMapper.selectOne(lqw);
    }

    @Override
    @Transactional
    public R<Long> createBook(WrongQuestionBook book) {
        // 检查是否已有默认错题本
        if (book.getIsDefault()) {
            WrongQuestionBook defaultBook = getDefaultBook(book.getUserId());
            if (defaultBook != null) {
                defaultBook.setIsDefault(false);
                bookMapper.updateById(defaultBook);
            }
        }

        bookMapper.insert(book);
        return R.ok(book.getId());
    }

    @Override
    @Transactional
    public R<Void> updateBook(WrongQuestionBook book) {
        // 检查是否设置为默认错题本
        if (book.getIsDefault()) {
            WrongQuestionBook defaultBook = getDefaultBook(book.getUserId());
            if (defaultBook != null && !defaultBook.getId().equals(book.getId())) {
                defaultBook.setIsDefault(false);
                bookMapper.updateById(defaultBook);
            }
        }

        bookMapper.updateById(book);
        return R.ok();
    }

    @Override
    @Transactional
    public R<Void> deleteBook(Long bookId) {
        WrongQuestionBook book = bookMapper.selectById(bookId);
        if (book == null) {
            return R.fail("错题本不存在");
        }

        // 不能删除默认错题本
        if (book.getIsDefault()) {
            return R.fail("不能删除默认错题本");
        }

        book.setDelFlag(1);
        bookMapper.updateById(book);
        return R.ok();
    }

    @Override
    @Transactional
    public R<Void> setDefaultBook(Long userId, Long bookId) {
        WrongQuestionBook currentDefault = getDefaultBook(userId);
        if (currentDefault != null && currentDefault.getId().equals(bookId)) {
            return R.ok();
        }

        // 取消当前默认错题本
        if (currentDefault != null) {
            currentDefault.setIsDefault(false);
            bookMapper.updateById(currentDefault);
        }

        // 设置新的默认错题本
        WrongQuestionBook newDefault = bookMapper.selectById(bookId);
        if (newDefault == null) {
            return R.fail("错题本不存在");
        }

        newDefault.setIsDefault(true);
        bookMapper.updateById(newDefault);
        return R.ok();
    }

    @Override
    public TableDataInfo<WrongQuestionRecord> pageRecordList(Long bookId,
                                                             Integer isMastered,
                                                             Integer typeId,
                                                             String questionText,
                                                             Integer difficulty,
                                                             PageQuery page) {
        // 构造查询条件
        MPJLambdaWrapperPlus<WrongQuestionRecord> lqw = new MPJLambdaWrapperPlus<WrongQuestionRecord>()
                .eq(WrongQuestionRecord::getBookId, bookId)
                .eqIfPresent(WrongQuestionRecord::getIsMastered, isMastered)
                .eq(WrongQuestionRecord::getDelFlag, 0)
                .orderByDesc(WrongQuestionRecord::getLastWrongTime);

        // 关联题目信息
        lqw.leftJoin(Question.class, Question::getId, WrongQuestionRecord::getQuestionId)
                .eq(typeId != null, Question::getTypeId, typeId)
                .eq(difficulty != null, Question::getDifficult, difficulty);

        if (StringUtils.isNotBlank(questionText)) {
            lqw.apply("MATCH(content) AGAINST({0} IN BOOLEAN MODE)",
                    "*" + questionText + "*");
        }

        // 分页查询
        Page<WrongQuestionRecord> result = recordMapper.selectJoinPage(page.build(), WrongQuestionRecord.class, lqw);

        if (result.getRecords() != null && !result.getRecords().isEmpty()) {
            // 批量查询相关数据
            List<Long> questionIds = result.getRecords().stream()
                    .map(WrongQuestionRecord::getQuestionId)
                    .distinct()
                    .collect(Collectors.toList());
            List<Long> answerIds = result.getRecords().stream()
                    .map(WrongQuestionRecord::getQuestionAnswerId)
                    .distinct()
                    .collect(Collectors.toList());
            List<Long> examIds = result.getRecords().stream()
                    .map(WrongQuestionRecord::getExamId)
                    .distinct()
                    .collect(Collectors.toList());

            // 批量查询题目信息
            Map<Long, QuestionDetailVo> questionMap = questionIds.isEmpty() ? Collections.emptyMap() :
                    questionMapper.selectQuestionDetailListByIds(questionIds).stream()
                            .collect(Collectors.toMap(QuestionDetailVo::getId, q -> q));

            Map<Long, ExamQuestionAnswers> answerMap = answerIds.isEmpty() ? Collections.emptyMap() :
                    answerMapper.selectBatchIds(answerIds).stream()
                            .collect(Collectors.toMap(ExamQuestionAnswers::getId, a -> a));

            Map<Long, Exam> examMap = examIds.isEmpty() ? Collections.emptyMap() :
                    examMapper.selectBatchIds(examIds).stream()
                            .collect(Collectors.toMap(Exam::getId, e -> e));

            // Set related data to records
            result.getRecords().forEach(record -> {
                record.setQuestion(questionMap.get(record.getQuestionId()));
                record.setAnswer(answerMap.get(record.getQuestionAnswerId()));
                record.setExam(examMap.get(record.getExamId()));
            });
        }

        return TableDataInfo.build(result);
    }

    @Override
    @Transactional
    public R<Void> addRecord(Long bookId, Long questionAnswerId) {
        ExamQuestionAnswers answer = answerMapper.selectById(questionAnswerId);
        if (answer == null) {
            return R.fail("作答记录不存在");
        }

        if (answer.getIsCorrect() == 1) {
            return R.fail("只有答错的题目才能加入错题本");
        }

        Question question = questionMapper.selectById(answer.getQuestionId());
        if (question == null) {
            return R.fail("题目不存在");
        }

        Exam exam = examMapper.selectById(answer.getExamId());
        if (exam == null) {
            return R.fail("考试不存在");
        }

        // 检查是否已存在
        LambdaQueryWrapper<WrongQuestionRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(WrongQuestionRecord::getBookId, bookId)
                .eq(WrongQuestionRecord::getQuestionId, answer.getQuestionId())
                .eq(WrongQuestionRecord::getDelFlag, 0);

        WrongQuestionRecord record = recordMapper.selectOne(lqw);
        if (record != null) {
            // 已存在则更新错误次数
            record.setWrongCount(record.getWrongCount() + 1);
            record.setLastWrongTime(new Date());
            recordMapper.updateById(record);
        } else {
            // 不存在则新增
            record = new WrongQuestionRecord();
            record.setBookId(bookId);
            record.setQuestionId(answer.getQuestionId());
            record.setQuestionAnswerId(questionAnswerId);
            record.setExamId(answer.getExamId());
            record.setExamName(exam.getTitle());
            record.setWrongCount(1);
            record.setLastWrongTime(new Date());
            record.setMasterLevel(0);
            record.setIsMastered(0);
            recordMapper.insert(record);
        }

        // 更新错题统计
        updateDailyStats(record.getBookId(), SecurityUtils.getUserId());

        return R.ok();
    }

    @Override
    @Transactional
    public R<Void> batchAddRecords(Long bookId, List<Long> questionAnswerIds) {
        for (Long answerId : questionAnswerIds) {
            addRecord(bookId, answerId);
        }
        return R.ok();
    }

    @Override
    @Transactional
    public R<Void> removeRecord(Long recordId) {
        WrongQuestionRecord record = recordMapper.selectById(recordId);
        if (record == null) {
            return R.fail("记录不存在");
        }

        record.setDelFlag(1);
        recordMapper.updateById(record);

        // 更新错题统计
        updateDailyStats(record.getBookId(), SecurityUtils.getUserId());

        return R.ok();
    }

    @Override
    @Transactional
    public R<Void> batchRemoveRecords(List<Long> recordIds) {
        for (Long recordId : recordIds) {
            removeRecord(recordId);
        }
        return R.ok();
    }

    @Override
    @Transactional
    public R<Void> markMastered(Long recordId, Integer mastered) {
        WrongQuestionRecord record = recordMapper.selectById(recordId);
        if (record == null) {
            return R.fail("记录不存在");
        }

        record.setIsMastered(mastered);
        if (mastered == 1) {
            record.setMasterLevel(100);
        } else {
            record.setMasterLevel(0);
        }
        recordMapper.updateById(record);

        // 更新错题统计
        updateDailyStats(record.getBookId(), SecurityUtils.getUserId());

        return R.ok();
    }

    @Override
    @Transactional
    public R<Void> updateRecordTags(Long recordId, String tagsJson) {
        WrongQuestionRecord record = recordMapper.selectById(recordId);
        if (record == null) {
            return R.fail("记录不存在");
        }

        record.setTagsJson(tagsJson);
        recordMapper.updateById(record);
        return R.ok();
    }

    @Override
    public R<Map<String, Object>> generatePractice(Long bookId, Integer count, Integer strategy) {
        // 策略: 1-随机 2-高频错题 3-近期错题 4-薄弱知识点
        LambdaQueryWrapper<WrongQuestionRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(WrongQuestionRecord::getBookId, bookId)
                .eq(WrongQuestionRecord::getDelFlag, 0);

        switch (strategy) {
            case 2:
                lqw.orderByDesc(WrongQuestionRecord::getWrongCount);
                break;
            case 3:
                lqw.orderByDesc(WrongQuestionRecord::getLastWrongTime);
                break;
            case 4:
                // 按掌握程度排序，掌握程度低的优先
                lqw.orderByAsc(WrongQuestionRecord::getMasterLevel);
                break;
            default:
                // 随机
                lqw.orderByAsc(WrongQuestionRecord::getWrongCount);
                break;
        }

        List<WrongQuestionRecord> records = recordMapper.selectList(lqw);
        if (records.isEmpty()) {
            return R.fail("错题本中没有题目");
        }

        // 限制数量
        if (records.size() > count) {
            records = records.subList(0, count);
        }

        // 获取题目详情
        List<Long> questionIds = records.stream()
                .map(WrongQuestionRecord::getQuestionId)
                .collect(Collectors.toList());
        List<Question> questions = questionMapper.selectBatchIds(questionIds);

        Map<Long, Question> questionMap = questions.stream()
                .collect(Collectors.toMap(Question::getId, q -> q));

        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("records", records);
        result.put("questions", questionMap);

        return R.ok(result);
    }

    @Override
    @Transactional
    public R<Void> submitPractice(Long recordId, String answer, Integer timeSpent) {
        WrongQuestionRecord record = recordMapper.selectById(recordId);
        if (record == null) {
            return R.fail("记录不存在");
        }

        // 创建练习记录
        WrongQuestionPractice practice = new WrongQuestionPractice();
        practice.setRecordId(recordId);
        practice.setBookId(record.getBookId());  // 设置bookId
        practice.setPracticeTime(new Date());
        practice.setIsCorrect(0);
        practice.setAnswer(answer);
        practice.setTimeSpent(timeSpent);
        practiceMapper.insert(practice);

        // 更新掌握程度
//        if (isCorrect) {
//            record.setMasterLevel(Math.min(100, record.getMasterLevel() + 20));
//            if (record.getMasterLevel() >= 80) {
//                record.setIsMastered(1);
//            }
//        } else {
            record.setMasterLevel(Math.max(0, record.getMasterLevel() + 1));
            record.setIsMastered(0);
            record.setWrongCount(record.getWrongCount() + 1);
            record.setLastWrongTime(new Date());
//        }

        recordMapper.updateById(record);

        // 更新错题统计
        updateDailyStats(record.getBookId(), SecurityUtils.getUserId());

        return R.ok();
    }

    @Override
    public TableDataInfo<WrongQuestionStats> pageStats(Long userId, Long bookId, PageQuery page) {
        LambdaQueryWrapper<WrongQuestionStats> lqw = Wrappers.lambdaQuery();
        lqw.eq(WrongQuestionStats::getUserId, userId)
                .eq(bookId != null, WrongQuestionStats::getBookId, bookId)
                .eq(WrongQuestionStats::getDelFlag, 0)
                .orderByDesc(WrongQuestionStats::getStatDate);

        Page<WrongQuestionStats> result = statsMapper.selectPage(page.build(), lqw);
        if (result.getRecords() != null && !result.getRecords().isEmpty()) {
            // 关联错题本信息
            List<Long> bookIds = result.getRecords().stream()
                    .map(WrongQuestionStats::getBookId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());

            if (!bookIds.isEmpty()) {
                Map<Long, WrongQuestionBook> bookMap = bookMapper.selectBatchIds(bookIds).stream()
                        .collect(Collectors.toMap(WrongQuestionBook::getId, b -> b));

                result.getRecords().forEach(stat -> {
                    if (stat.getBookId() != null) {
                        stat.setBook(bookMap.get(stat.getBookId()));
                    }
                });
            }
        }

        return TableDataInfo.build(result);
    }

    @Override
    public R<Map<String, Object>> getOverviewStats(Long userId, Long bookId) {
        Map<String, Object> result = new HashMap<>();

        // 总错题数
        LambdaQueryWrapper<WrongQuestionRecord> recordLqw = Wrappers.lambdaQuery();
        recordLqw.eq(WrongQuestionRecord::getCreateBy, userId)
                .eq(bookId != null, WrongQuestionRecord::getBookId, bookId)
                .eq(WrongQuestionRecord::getDelFlag, 0);
        Long totalCount = recordMapper.selectCount(recordLqw);
        result.put("totalCount", totalCount);

        // 已掌握错题数
        recordLqw.eq(WrongQuestionRecord::getIsMastered, 1);
        Long masteredCount = recordMapper.selectCount(recordLqw);
        result.put("masteredCount", masteredCount);

        // 本周新增错题数
        recordLqw = Wrappers.lambdaQuery();
        recordLqw.eq(WrongQuestionRecord::getCreateBy, userId)
                .eq(bookId != null, WrongQuestionRecord::getBookId, bookId)
                .eq(WrongQuestionRecord::getDelFlag, 0)
                .ge(WrongQuestionRecord::getCreateTime, DateUtils.getWeekStart())
                .le(WrongQuestionRecord::getCreateTime, DateUtils.getWeekEnd());
        Long weeklyNewCount = recordMapper.selectCount(recordLqw);
        result.put("weeklyNewCount", weeklyNewCount);

        // 本周复习正确率
        LambdaQueryWrapper<WrongQuestionPractice> practiceLqw = Wrappers.lambdaQuery();
        practiceLqw.eq(WrongQuestionPractice::getCreateBy, userId)
                .eq(bookId != null, WrongQuestionPractice::getBookId, bookId)
                .eq(WrongQuestionPractice::getDelFlag, 0)
                .ge(WrongQuestionPractice::getPracticeTime, DateUtils.getWeekStart())
                .le(WrongQuestionPractice::getPracticeTime, DateUtils.getWeekEnd());

        Long totalPractice = practiceMapper.selectCount(practiceLqw);
        if (totalPractice > 0) {
            practiceLqw.eq(WrongQuestionPractice::getIsCorrect, 1);
            Long correctPractice = practiceMapper.selectCount(practiceLqw);
            result.put("weeklyAccuracy", new BigDecimal(correctPractice * 100 / totalPractice).setScale(2));
        } else {
            result.put("weeklyAccuracy", BigDecimal.ZERO);
        }

        return R.ok(result);
    }

    @Override
    public R<List<Map<String, Object>>> getKnowledgeStats(Long userId, Long bookId) {
        // 获取知识点分布统计
        LambdaQueryWrapper<WrongQuestionRecord> recordLqw = Wrappers.lambdaQuery();
        recordLqw.eq(WrongQuestionRecord::getCreateBy, userId)
                .eq(bookId != null, WrongQuestionRecord::getBookId, bookId)
                .eq(WrongQuestionRecord::getDelFlag, 0);

        List<WrongQuestionRecord> records = recordMapper.selectList(recordLqw);
        if (records.isEmpty()) {
            return R.ok(Collections.emptyList());
        }

        // 获取题目关联的知识点
        List<Long> questionIds = records.stream()
                .map(WrongQuestionRecord::getQuestionId)
                .collect(Collectors.toList());

        LambdaQueryWrapper<QuestionCategoryRelation> relationLqw = Wrappers.lambdaQuery();
        relationLqw.in(QuestionCategoryRelation::getQuestionId, questionIds)
                .eq(QuestionCategoryRelation::getIsKnowledge, 1)
                .eq(QuestionCategoryRelation::getDelFlag, 0);

        List<QuestionCategoryRelation> relations = relationMapper.selectList(relationLqw);
        if (relations.isEmpty()) {
            return R.ok(Collections.emptyList());
        }

        // 获取知识点详情
        List<Long> categoryIds = relations.stream()
                .map(QuestionCategoryRelation::getCategoryId)
                .distinct()
                .collect(Collectors.toList());

        Map<Long, QuestionCategory> categoryMap = categoryMapper.selectBatchIds(categoryIds).stream()
                .collect(Collectors.toMap(QuestionCategory::getId, c -> c));

        // 统计每个知识点的错题数
        Map<Long, Long> knowledgeCountMap = relations.stream()
                .collect(Collectors.groupingBy(
                        QuestionCategoryRelation::getCategoryId,
                        Collectors.counting()
                ));

        // 构建返回结果
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map.Entry<Long, Long> entry : knowledgeCountMap.entrySet()) {
            QuestionCategory category = categoryMap.get(entry.getKey());
            if (category != null) {
                Map<String, Object> stat = new HashMap<>();
                stat.put("knowledgeId", category.getId());
                stat.put("knowledgeName", category.getName());
                stat.put("count", entry.getValue());
                result.add(stat);
            }
        }

        // 按错题数降序排序
        result.sort((a, b) -> ((Long) b.get("count")).compareTo((Long) a.get("count")));

        return R.ok(result);
    }

    @Override
    public R<List<Map<String, Object>>> getTypeStats(Long userId, Long bookId) {
        // 获取题型分布统计
        LambdaQueryWrapper<WrongQuestionRecord> recordLqw = Wrappers.lambdaQuery();
        recordLqw.eq(WrongQuestionRecord::getCreateBy, userId)
                .eq(bookId != null, WrongQuestionRecord::getBookId, bookId)
                .eq(WrongQuestionRecord::getDelFlag, 0);

        List<WrongQuestionRecord> records = recordMapper.selectList(recordLqw);
        if (records.isEmpty()) {
            return R.ok(Collections.emptyList());
        }

        // 获取题目详情
        List<Long> questionIds = records.stream()
                .map(WrongQuestionRecord::getQuestionId)
                .collect(Collectors.toList());

        Map<Long, Question> questionMap = questionMapper.selectBatchIds(questionIds).stream()
                .collect(Collectors.toMap(Question::getId, q -> q));

        // 获取题型详情
        Set<Long> typeIds = questionMap.values().stream()
                .map(Question::getTypeId)
                .collect(Collectors.toSet());

        Map<Long, QuestionType> typeMap = typeMapper.selectBatchIds(typeIds).stream()
                .collect(Collectors.toMap(QuestionType::getId, t -> t));

        // 统计每个题型的错题数
        Map<Long, Long> typeCountMap = questionMap.values().stream()
                .collect(Collectors.groupingBy(
                        Question::getTypeId,
                        Collectors.counting()
                ));

        // 构建返回结果
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map.Entry<Long, Long> entry : typeCountMap.entrySet()) {
            QuestionType type = typeMap.get(entry.getKey());
            if (type != null) {
                Map<String, Object> stat = new HashMap<>();
                stat.put("typeId", type.getId());
                stat.put("typeName", type.getName());
                stat.put("count", entry.getValue());
                result.add(stat);
            }
        }

        // 按错题数降序排序
        result.sort((a, b) -> ((Long) b.get("count")).compareTo((Long) a.get("count")));

        return R.ok(result);
    }

    @Override
    public R<List<QuestionDetailVo>> recommendQuestions(Long recordId, Integer count, Integer strategy) {
        WrongQuestionRecord record = recordMapper.selectById(recordId);
        if (record == null) {
            return R.fail("记录不存在");
        }

        Question question = questionMapper.selectById(record.getQuestionId());
        if (question == null) {
            return R.fail("题目不存在");
        }

        // 策略: 1-相似题目 2-同知识点不同难度 3-同难度不同知识点 4-随机推荐
        List<QuestionDetailVo> recommended = new ArrayList<>();

        switch (strategy) {
            case 1:
                // 相似题目
                recommended = questionService.findSimilarQuestions(question.getId(), count);
                break;
            case 2:
                // 同知识点不同难度
                recommended = questionService.findByKnowledgeDifferentDifficulty(
                        question.getId(),
                        question.getTypeId(),
                        question.getDifficult(),
                        count
                );
                break;
            case 3:
                // 同难度不同知识点
                recommended = questionService.findByDifficultyDifferentKnowledge(
                        question.getId(),
                        question.getTypeId(),
                        question.getDifficult(),
                        count
                );
                break;
            default:
                // 随机推荐
                recommended = questionService.findRandomQuestions(
                        question.getTypeId(),
                        count
                );
                break;
        }

        return R.ok(recommended);
    }

    // 更新每日错题统计
    private void updateDailyStats(Long bookId, Long userId) {
        LocalDate today = LocalDate.now();
        Date statDate = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());

        LambdaQueryWrapper<WrongQuestionStats> lqw = Wrappers.lambdaQuery();
        lqw.eq(WrongQuestionStats::getUserId, userId)
                .eq(bookId != null, WrongQuestionStats::getBookId, bookId)
                .eq(WrongQuestionStats::getStatDate, statDate)
                .eq(WrongQuestionStats::getDelFlag, 0);

        WrongQuestionStats stats = statsMapper.selectOne(lqw);
        if (stats == null) {
            stats = new WrongQuestionStats();
            stats.setUserId(userId);
            stats.setBookId(bookId);
            stats.setStatDate(statDate);
            stats.setTotalCount(0L);
            stats.setNewCount(0L);
            stats.setReviewCount(0L);
            stats.setMasteredCount(0L);
            stats.setAccuracyRate(BigDecimal.ZERO);
            statsMapper.insert(stats);
        }

        // 更新总错题数
        LambdaQueryWrapper<WrongQuestionRecord> recordLqw = Wrappers.lambdaQuery();
        recordLqw.eq(WrongQuestionRecord::getCreateBy, userId)
                .eq(bookId != null, WrongQuestionRecord::getBookId, bookId)
                .eq(WrongQuestionRecord::getDelFlag, 0);
        stats.setTotalCount(recordMapper.selectCount(recordLqw));

        // 更新今日新增错题数
        recordLqw.ge(WrongQuestionRecord::getCreateTime, statDate);
        stats.setNewCount(recordMapper.selectCount(recordLqw));

        // 更新已掌握错题数
        recordLqw = Wrappers.lambdaQuery();
        recordLqw.eq(WrongQuestionRecord::getCreateBy, userId)
                .eq(bookId != null, WrongQuestionRecord::getBookId, bookId)
                .eq(WrongQuestionRecord::getIsMastered, 1)
                .eq(WrongQuestionRecord::getDelFlag, 0);
        stats.setMasteredCount(recordMapper.selectCount(recordLqw));

        // 更新今日复习正确率
        LambdaQueryWrapper<WrongQuestionPractice> practiceLqw = Wrappers.lambdaQuery();
        practiceLqw.inSql(WrongQuestionPractice::getRecordId,
                        "select id from wrong_question_records where book_id = " + bookId)
                .eq(WrongQuestionPractice::getCreateBy, userId)
                .ge(WrongQuestionPractice::getPracticeTime, statDate)
                .eq(WrongQuestionPractice::getDelFlag, 0);

        Long totalPractice = practiceMapper.selectCount(practiceLqw);
        if (totalPractice > 0) {
            practiceLqw.eq(WrongQuestionPractice::getIsCorrect, 1);
            Long correctPractice = practiceMapper.selectCount(practiceLqw);
            stats.setAccuracyRate(new BigDecimal(correctPractice * 100 / totalPractice).setScale(2));
            stats.setReviewCount(totalPractice);
        } else {
            stats.setAccuracyRate(BigDecimal.ZERO);
            stats.setReviewCount(0L);
        }

        statsMapper.updateById(stats);
    }

    @Override
    public R<List<ExamQuestionAnswers>> getWrongAnswers(Long userId) {
        // 查询用户最近的考试记录
        LambdaQueryWrapper<ExamStudentRecord> recordLqw = Wrappers.lambdaQuery();
        recordLqw.eq(ExamStudentRecord::getUserId, userId)
                .eq(ExamStudentRecord::getStatus, 2) // 已提交的考试
                .orderByDesc(ExamStudentRecord::getSubmitTime);

        List<ExamStudentRecord> examRecords = examStudentRecordMapper.selectList(recordLqw);
        if (examRecords.isEmpty()) {
            return R.ok(Collections.emptyList());
        }

        // 获取考试ID列表
        List<Long> examIds = examRecords.stream()
                .map(ExamStudentRecord::getExamId)
                .collect(Collectors.toList());

        // 查询这些考试中的错题
        LambdaQueryWrapper<ExamQuestionAnswers> answerLqw = Wrappers.lambdaQuery();
        answerLqw.in(ExamQuestionAnswers::getExamId, examIds)
                .eq(ExamQuestionAnswers::getUserId, userId)
                .eq(ExamQuestionAnswers::getIsCorrect, 0) // 错误的题目
                .eq(ExamQuestionAnswers::getDelFlag, 0)
                .orderByDesc(ExamQuestionAnswers::getExamId)
                .orderByDesc(ExamQuestionAnswers::getQuestionId);

        List<ExamQuestionAnswers> wrongAnswers = answerMapper.selectList(answerLqw);

        // 关联题目和考试信息
        if (!wrongAnswers.isEmpty()) {
            List<Long> questionIds = wrongAnswers.stream()
                    .map(ExamQuestionAnswers::getQuestionId)
                    .distinct()
                    .collect(Collectors.toList());

            List<Long> distinctExamIds = wrongAnswers.stream()
                    .map(ExamQuestionAnswers::getExamId)
                    .distinct()
                    .collect(Collectors.toList());

            Map<Long, Question> questionMap = questionMapper.selectBatchIds(questionIds).stream()
                    .collect(Collectors.toMap(Question::getId, q -> q));

            Map<Long, Exam> examMap = examMapper.selectBatchIds(distinctExamIds).stream()
                    .collect(Collectors.toMap(Exam::getId, e -> e));

            wrongAnswers.forEach(answer -> {
                answer.setQuestion(questionMap.get(answer.getQuestionId()));
                answer.setExam(examMap.get(answer.getExamId()));
            });
        }

        return R.ok(wrongAnswers);
    }

    @Override
    @Transactional
    public R<Void> syncWrongAnswers(Long bookId, List<Long> answerIds) {
        if (answerIds == null || answerIds.isEmpty()) {
            return R.fail("请选择要同步的错题");
        }

        // 获取错题本信息
        WrongQuestionBook book = bookMapper.selectById(bookId);
        if (book == null) {
            return R.fail("错题本不存在");
        }

        // 批量查询作答记录
        List<ExamQuestionAnswers> answers = answerMapper.selectBatchIds(answerIds);
        if (answers.isEmpty()) {
            return R.fail("未找到对应的作答记录");
        }

        // 获取考试和题目信息
        List<Long> examIds = answers.stream()
                .map(ExamQuestionAnswers::getExamId)
                .distinct()
                .collect(Collectors.toList());

        List<Long> questionIds = answers.stream()
                .map(ExamQuestionAnswers::getQuestionId)
                .collect(Collectors.toList());

        Map<Long, Exam> examMap = examMapper.selectBatchIds(examIds).stream()
                .collect(Collectors.toMap(Exam::getId, e -> e));

        Map<Long, Question> questionMap = questionMapper.selectBatchIds(questionIds).stream()
                .collect(Collectors.toMap(Question::getId, q -> q));

        // 同步错题到错题本
        int successCount = 0;
        for (ExamQuestionAnswers answer : answers) {
            Exam exam = examMap.get(answer.getExamId());
            Question question = questionMap.get(answer.getQuestionId());

            if (exam == null || question == null) {
                continue;
            }

            // 检查是否已存在
            LambdaQueryWrapper<WrongQuestionRecord> lqw = Wrappers.lambdaQuery();
            lqw.eq(WrongQuestionRecord::getBookId, bookId)
                    .eq(WrongQuestionRecord::getQuestionId, answer.getQuestionId())
                    .eq(WrongQuestionRecord::getDelFlag, 0);

            WrongQuestionRecord record = recordMapper.selectOne(lqw);
            if (record != null) {
                // 已存在则更新错误次数
                record.setWrongCount(record.getWrongCount() + 1);
                record.setLastWrongTime(new Date());
                recordMapper.updateById(record);
            } else {
                // 不存在则新增
                record = new WrongQuestionRecord();
                record.setBookId(bookId);
//                record.setUserId(book.getUserId());
                record.setQuestionId(answer.getQuestionId());
                record.setQuestionAnswerId(answer.getId());
                record.setExamId(answer.getExamId());
                record.setExamName(exam.getTitle());
                record.setWrongCount(1);
                record.setLastWrongTime(new Date());
                record.setMasterLevel(0);
                record.setIsMastered(0);
                recordMapper.insert(record);
            }
            successCount++;
        }

        // 更新错题统计
        updateDailyStats(bookId, book.getUserId());

        return R.ok(null, "成功同步 " + successCount + " 道错题");
    }
}